package fnsvr

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strconv"
)

// post请求，返回结构体
func HttpPost[PT any, RT any](postUrl string, param *PT) (*RT, error) {
	data := url.Values{}

	jsonBytes, err := json.Marshal(param)
	if err != nil {
		Log().Error("HttpPost", "url", postUrl, "param", param, "err", err)
		return nil, err
	}

	var kv map[string]any
	err = json.Unmarshal(jsonBytes, &kv)
	if err != nil {
		Log().Error("HttpPost#1", "url", postUrl, "param", param, "err", err)
		return nil, err
	}

	for k, v := range kv {
		data.Set(k, AnyToString(v))
	}
	encodedData := data.Encode() // 自动URL编码

	// 创建请求体
	body := bytes.NewBufferString(encodedData)

	req, err := http.NewRequest("POST", postUrl, body)
	if err != nil {
		Log().Error("HttpPost#2", "url", postUrl, "param", param, "err", err)
		return nil, err
	}
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	// 发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		Log().Error("HttpPost#9", "url", postUrl, "param", param, "err", err)
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		Log().Error("HttpPost#3", "url", postUrl, "param", param, "err", err, "statusCode", resp.StatusCode)
		return nil, errors.New("Error: received status code " + strconv.Itoa(resp.StatusCode))
	}

	// 处理响应
	respBody, _ := io.ReadAll(resp.Body)

	var result RT
	err = json.Unmarshal(respBody, &result)
	if err != nil {
		Log().Error("HttpPost#4", "url", postUrl, "param", param, "err", err, "respBody", string(respBody))
		return nil, err
	}

	return &result, nil
}

// post请求，返回结构体
func HttpPostJson[PT any, RT any](postUrl string, param *PT) (*RT, error) {

	jsonBytes, err := json.Marshal(param)
	if err != nil {
		return nil, err
	}

	// 创建请求体

	req, err := http.NewRequest("POST", postUrl, bytes.NewBuffer(jsonBytes))
	if err != nil {
		Log().Error("HttpPostJson", "url", postUrl, "param", param, "err", err)
		return nil, err
	}
	req.Header.Set("Content-Type", "application/json")

	// 发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		Log().Error("HttpPostJson#9", "url", postUrl, "param", param, "err", err)
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != 200 {
		Log().Error("HttpPostJson#3", "url", postUrl, "param", param, "err", err, "statusCode", resp.StatusCode)
		return nil, errors.New("Error: received status code " + strconv.Itoa(resp.StatusCode))
	}

	// 处理响应
	respBody, _ := io.ReadAll(resp.Body)

	var result RT
	err = json.Unmarshal(respBody, &result)
	if err != nil {
		Log().Error("HttpPostJson#4", "url", postUrl, "param", param, "err", err, "respBody", string(respBody))
		return nil, err
	}

	return &result, nil
}

// get请求，返回结构体
// 创建参数键值对
/*
	params := url.Values{}
	params.Add("key1", "value1")
	params.Add("key2", "value2")
	params.Add("page", "1")
*/
func HttpGet[RT any](url string, params url.Values) (*RT, error) {

	// 拼接完整URL
	fullUrl := url + "?" + params.Encode()

	return HttpGetNoParam[RT](fullUrl)

}

// get请求，返回结构体
func HttpGetNoParam[RT any](url string) (*RT, error) {
	// 发起GET请求
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// 读取响应
	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	var result RT
	err = json.Unmarshal(respBody, &result)
	if err != nil {
		return nil, err
	}

	return &result, nil
}

// 从指定的url获取数据到内存缓冲区
func HttpGetBytes(url string) ([]byte, error) {
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("HTTP request failed with status: %s", resp.Status)
	}

	return io.ReadAll(resp.Body)
}
